Skip to content

fix: writing data via usb on windows #89

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

RedCommander735
Copy link

@RedCommander735 RedCommander735 commented Jul 27, 2025

ref #25
Seems to have been a combination of both. This works on my machine

Summary by Sourcery

Improve USB HID write functionality on Windows to handle data larger than single reports and correct a function naming typo.

Bug Fixes:

  • Loop HID writes on Windows to send data in 64-byte chunks with an offset header until the entire payload is sent
  • Fix typo in main.rs by renaming gnerate_payload to generate_payload

Enhancements:

  • Add prepend_byte_and_offset helper to construct proper HID report packets

Copy link

sourcery-ai bot commented Jul 27, 2025

Reviewer's Guide

Introduce Windows-specific chunked USB HID write logic by looping writes with report ID prepended, add a helper to split data into 64-byte packets, and correct a typo in the payload generation function name.

Class diagram for updated USB HID write logic

classDiagram
    class HidDevice {
        +write(&self, data: &[u8]) -> Result<usize>
    }
    class usb_hid {
        +write_raw(device: &HidDevice, data: &[u8]) -> Result<()>  
        +prepend_byte_and_offset(data: &[u8], offset: usize) -> [u8; 65]
    }
    HidDevice <.. usb_hid : uses
Loading

Class diagram for corrected payload generation function

classDiagram
    class Args {
        +config: Option<String>
    }
    class main {
        +generate_payload(args: &mut Args) -> Result<PayloadBuffer>
        +write_payload(transport: &TransportProtocol, payload: PayloadBuffer) -> Result<()>
    }
    Args <.. main : uses
Loading

File-Level Changes

Change Details Files
Implement chunked USB HID writes on Windows with a helper
  • Wrap write_raw in #[cfg(windows)] loop using prepend_byte_and_offset
  • Fall back to a single write on non-Windows with #[cfg(not(windows))]
  • Update incomplete-write assertion to check the cumulative written bytes
  • Add prepend_byte_and_offset function for 64-byte chunk preparation
src/usb_hid.rs
Fix typo in payload generation function
  • Rename gnerate_payload to generate_payload in main.rs call site
  • Update the function definition name accordingly
src/main.rs

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @RedCommander735 - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Potential buffer overrun in chunked write loop. (link)
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/usb_hid.rs:107` </location>
<code_context>
+    {
+        written = 0;
+
+        while written < data.len() {
+            let new_data: &[u8] = &prepend_byte_and_offset(data, written);
+            let n = device.write(new_data).context("write payload")?;
+            written = written + n - 1;
</code_context>

<issue_to_address>
Potential buffer overrun in chunked write loop.

If less than 64 bytes remain, slicing 'data[offset..offset + 64]' will panic. Please handle the final chunk to prevent out-of-bounds access.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@RedCommander735
Copy link
Author

@sourcery-ai review

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @RedCommander735 - I've reviewed your changes - here's some feedback:

  • The write loop on Windows subtracts 1 from each write count, so if device.write ever returns 0 or 1 this could spin indefinitely—consider erroring or breaking out when n <= 1 to avoid infinite loops.
  • The hardcoded report ID (0x0) in prepend_byte_and_offset limits flexibility—consider parameterizing this value or documenting its assumptions for different HID devices.
  • You might extract the chunking and packet-preparation into a reusable iterator or helper struct to make the write logic more declarative and testable, reducing manual loop complexity.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The write loop on Windows subtracts 1 from each write count, so if device.write ever returns 0 or 1 this could spin indefinitely—consider erroring or breaking out when n <= 1 to avoid infinite loops.
- The hardcoded report ID (0x0) in prepend_byte_and_offset limits flexibility—consider parameterizing this value or documenting its assumptions for different HID devices.
- You might extract the chunking and packet-preparation into a reusable iterator or helper struct to make the write logic more declarative and testable, reducing manual loop complexity.

## Individual Comments

### Comment 1
<location> `src/usb_hid.rs:107` </location>
<code_context>
+    {
+        written = 0;
+
+        while written < data.len() {
+            let new_data: &[u8] = &prepend_byte_and_offset(data, written);
+            let n = device.write(new_data).context("write payload")?;
</code_context>

<issue_to_address>
Potential for infinite loop if device.write returns 1.

Since written does not increase when device.write returns 1, the loop may never terminate. Please add a check or safeguard for this scenario.
</issue_to_address>

### Comment 2
<location> `src/usb_hid.rs:128` </location>
<code_context>
     Ok(())
 }
+
+fn prepend_byte_and_offset(data: &[u8], offset: usize) -> [u8; 65] {
+    let mut result: [u8; 65] = [0u8; 65];
+    result[1] = 0x0;
</code_context>

<issue_to_address>
Possible out-of-bounds panic if offset > data.len().

Add a debug assertion or explicit check to ensure offset does not exceed data.len().
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

data.len()
);

Ok(())
}

fn prepend_byte_and_offset(data: &[u8], offset: usize) -> [u8; 65] {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Possible out-of-bounds panic if offset > data.len().

Add a debug assertion or explicit check to ensure offset does not exceed data.len().

@RedCommander735
Copy link
Author

@sourcery-ai review

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @RedCommander735 - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/usb_hid.rs:107` </location>
<code_context>
+    {
+        written = 0;
+
+        while written < data.len() {
+            let new_data: &[u8] = &prepend_byte_and_offset(data, written);
+            let n = device.write(new_data).context("write payload")?;
+            written = written + n - 1;
+        }
+    }
</code_context>

<issue_to_address>
Potential off-by-one error in written byte calculation.

Subtracting 1 from 'written + n' may cause incorrect loop termination or skipped bytes, particularly when 'n' is 0 or 1. Please verify if this adjustment is needed.
</issue_to_address>

### Comment 2
<location> `src/usb_hid.rs:131` </location>
<code_context>
+fn prepend_byte_and_offset(data: &[u8], offset: usize) -> [u8; 65] {
+    let mut result: [u8; 65] = [0u8; 65];
+    result[1] = 0x0;
+    if offset > data.len() {
+        return result;
+    }
+    if data.len() - offset < 64 {
</code_context>

<issue_to_address>
Returning a zeroed buffer when offset exceeds data length may mask errors.

Returning a zeroed buffer in this case may hide upstream logic errors. Instead, consider returning an error or panicking to make the issue explicit.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +107 to +110
while written < data.len() {
let new_data: &[u8] = &prepend_byte_and_offset(data, written);
let n = device.write(new_data).context("write payload")?;
written = written + n - 1;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Potential off-by-one error in written byte calculation.

Subtracting 1 from 'written + n' may cause incorrect loop termination or skipped bytes, particularly when 'n' is 0 or 1. Please verify if this adjustment is needed.

Comment on lines +131 to +132
if offset > data.len() {
return result;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Returning a zeroed buffer when offset exceeds data length may mask errors.

Returning a zeroed buffer in this case may hide upstream logic errors. Instead, consider returning an error or panicking to make the issue explicit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant